package loupan

import (
	"errors"
	"fmt"
	"hft/Database/admin"
	"hft/Database/admin/phone"
	"hft/Http/Models/dao"
	"hft/Http/Models/request"
	"hft/Http/Services/base"
	"hft/Http/Services/loupan/loupan_dao"
	"hft/Http/Services/loupan/loupan_model"
	"hft/Http/Services/loupan/loupan_utils"
	utils "hft/Http/Utils"
	"hft/e"
	"hft/global"
	"hft/tools"
	"hft/tools/phone/api"
	"hft/tools/phone/model"
	"regexp"
	"strconv"
	"strings"

	"gorm.io/gorm"
)

type NewLouPan struct{}

func (*NewLouPan) GetLouPanList(paginate *request.LouPaPaginate, claims tools.BaseClaims) (data *utils.Page, err error) {
	var list []*loupan_model.DBLouPan
	var newList = make([]*loupan_model.LouPan, 0)
	account, err := base.FindAccount(claims, global.OC_DB)
	if err != nil {
		return nil, err
	}
	err = global.OC_DB.Model(&admin.LouPan{}).Scopes(dao.LouPanDao.GetNewLouPanList(fmt.Sprintf("%v%%", account.RegionLink), paginate, global.OC_DB)).Find(&list).Offset(-1).Limit(-1).Count(&paginate.Total).Error
	if err != nil {
		return nil, errors.New(e.ErrorInfo)
	}
	tags := loupan_dao.FindTag(list, global.OC_DB)
	dis := loupan_dao.FindRank(list, global.OC_DB)
	for _, v := range list {
		var newTags []string
		for _, j := range tags {
			if j.LouPanID == v.ID {
				newTags = append(newTags, j.Name)
			}
		}
		var disList []*admin.Disadvantage
		for _, d := range dis {
			if d.LouPanID == v.ID {
				disList = append(disList, &admin.Disadvantage{
					Name:      d.Name,
					TextColor: d.TextColor,
					Cover:     global.OC_CONFIG.AliyunOSS.BucketUrl + d.Cover,
				})
			}
		}
		newList = append(newList, &loupan_model.LouPan{
			ID:              int(v.ID),
			Name:            v.Name,
			Sort:            v.Sort,
			Cover:           global.OC_CONFIG.AliyunOSS.BucketUrl + v.Cover,
			BelongName:      v.BelongName,
			Grounding:       v.Grounding,
			ReferencePrice:  v.ReferencePrice,
			Status:          int(v.SellStatus.StatusCode),
			StatusName:      v.SellStatus.Name,
			StatusColor:     v.SellStatus.BackColor,
			StatusTextColor: v.SellStatus.TextColor,
			CreateTime:      v.CreateTime.Format("20060102150405"),
			ActiveLastTime:  v.ActiveLastUpdate,
			Region:          v.Region,
			Residential:     v.Garrison,
			SellPhone:       global.OC_CONFIG.Phone.Account + "-" + v.SellLouPanInfo.SellPhone,
			MaxArea:         v.MaxArea,
			MinArea:         v.MinArea,
			Tags:            newTags,
			Disadvantage:    disList,
			WhatsApp:        v.WhatsApp,
		})
	}
	paginate.Data = newList
	return &paginate.Page, nil
}

func (*NewLouPan) GetGarrison(paginate *loupan_model.GetGarrison, claims tools.BaseClaims) (data *utils.Page, err error) {
	var louPan *admin.LouPan
	if err = global.OC_DB.First(&louPan, paginate.LouID).Error; err != nil {
		return nil, errors.New(e.LouPanNotExist)
	}
	account, err := base.FindAccount(claims, global.OC_DB)
	if err != nil {
		return nil, err
	}
	if match, _ := regexp.MatchString(fmt.Sprintf("^%v", account.RegionLink), louPan.RegionLink); !match {
		return nil, errors.New(e.NoRightToOpera)
	}
	var brokers []*admin.Account
	var newBrokers = make([]*loupan_model.Garrison, 0)
	global.OC_DB.Model(&louPan).Association("Accounts").Find(&brokers)
	for _, v := range brokers {
		newBrokers = append(newBrokers, &loupan_model.Garrison{
			ID:       v.ID,
			Phone:    v.Phone,
			RealName: v.RealName,
			Avatar:   global.OC_CONFIG.AliyunOSS.BucketUrl + v.Avatar,
		})
	}
	paginate.Data = newBrokers
	return &paginate.Page, nil
}

// 解除驻守
func (*NewLouPan) ReleaseBroker(data *loupan_model.ReleaseBody, claims tools.BaseClaims) (err error) {
	account, err := base.FindAccount(claims, global.OC_DB)
	if err != nil {
		return err
	}
	var louPan *admin.LouPan
	global.OC_DB.First(&louPan, data.LouID)
	// 判断是否有权解除该楼盘的信息
	if ok, _ := regexp.MatchString(fmt.Sprintf("^%v", account.RegionLink), louPan.RegionLink); !ok {
		return errors.New(e.NoRightToOpera)
	}
	// 判断是否有权解除该经纪人的信息
	var broker *admin.Account
	global.OC_DB.First(&broker, data.BrokerID)
	if ok, _ := regexp.MatchString(fmt.Sprintf("^%v", account.AccountLink), broker.AccountLink); !ok {
		return errors.New(e.NoRightToOpera)
	}
	// 开启事务
	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {
		// 删除该楼盘与经纪人的中间表信息
		if err = tx.Exec(fmt.Sprintf("delete from `hft_account_lou_pan` where account_id = %v and lou_pan_id = %v", broker.ID, louPan.ID)).Error; err != nil {
			return errors.New(e.ErrorInfo)
		}
		// 删除对应的分机号记载
		var phoneDnAudio *phone.PhoneAudio
		err = tx.Where("lou_id = ?", data.LouID).First(&phoneDnAudio).Error
		if err != nil {
			return errors.New(e.LouPanNotExist)
		}
		var managerPhone string
		if account.RoleId != 32 {
			var strArr = strings.Split(louPan.RegionLink, ",")
			manage_city, _ := strconv.Atoi(strArr[3])
			var manager_region *admin.Region
			global.OC_DB.Select("id, manage_id").First(&manager_region, manage_city)
			if manager_region.ManageId != 0 {
				var manager_account *admin.Account
				global.OC_DB.Select("id,phone").First(&manager_account, manager_region.ManageId)
				managerPhone = manager_account.Phone
			} else {
				managerPhone = account.Phone
			}
		} else {
			managerPhone = account.Phone
		}
		var newBroker = loupan_utils.DeleteBrokerPhoneBelongThisLouPan(broker.Phone, managerPhone, phoneDnAudio.Broker)
		if err = tx.Model(&phone.PhoneAudio{}).Where("id = ?", phoneDnAudio.ID).Updates(map[string]interface{}{
			"broker": fmt.Sprintf(",%v,", newBroker),
		}).Error; err != nil {
			return errors.New(e.ErrorInfo)
		}
		// 更新远端的400电话
		var list []*model.Row
		var aniAudio = ""
		var dniAudio = ""
		if phoneDnAudio.Audit == 2 { //审核通过就添加语音，不通过不添加
			aniAudio = fmt.Sprintf("%v_ani.wav", phoneDnAudio.ID)
			dniAudio = fmt.Sprintf("%v_dni.wav", phoneDnAudio.ID)
		}
		list = append(list, &model.Row{Dn: fmt.Sprintf("%v", phoneDnAudio.ID), Tel: strings.Join(strings.Split(newBroker, ","), "|"), TransType: "rnd", AniVoiceName: aniAudio, DniVoiceName: dniAudio})
		code := api.PhoneVirtual.AddOrEditPhone(list)
		if code != "0" {
			return errors.New(e.ErrorInfo)
		}
		return nil
	})
	return err
}

// 添加驻守人员
func (*NewLouPan) AddNewBroker(data *loupan_model.AddBody, claims tools.BaseClaims) (err error) {
	account, err := base.FindAccount(claims, global.OC_DB)
	if err != nil {
		return err
	}
	var louPan *admin.LouPan
	global.OC_DB.First(&louPan, data.LouID)
	// 判断是否有权修改该楼盘的信息
	if ok, _ := regexp.MatchString(fmt.Sprintf("^%v", account.RegionLink), louPan.RegionLink); !ok {
		return errors.New(e.NoRightToOpera)
	}
	// 判断是否有权添加该经纪人的信息到楼盘
	var brokers []*admin.Account
	global.OC_DB.Find(&brokers, data.Brokers)
	if ok := loupan_utils.HasPowerToOperaBrokers(fmt.Sprintf("%v%v,", account.AccountLink, account.ID), brokers); !ok {
		return errors.New(e.NoRightToOpera)
	}
	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {
		// 先添加中间表
		if err = tx.Model(&louPan).Association("Accounts").Append(&brokers); err != nil {
			return errors.New(e.ErrorInfo)
		}
		// 然后添加楼盘分机中间表
		var phoneDnAudio *phone.PhoneAudio
		err = tx.Where("lou_id = ?", data.LouID).First(&phoneDnAudio).Error
		if err != nil {
			return errors.New(e.LouPanNotExist)
		}
		// 获取新的目的码
		var managerPhone string
		if account.RoleId != 32 {
			var strArr = strings.Split(louPan.RegionLink, ",")
			manage_city, _ := strconv.Atoi(strArr[3])
			var manager_region *admin.Region
			global.OC_DB.Select("id, manage_id").First(&manager_region, manage_city)
			if manager_region.ManageId != 0 {
				var manager_account *admin.Account
				global.OC_DB.Select("id,phone").First(&manager_account, manager_region.ManageId)
				managerPhone = manager_account.Phone
			} else {
				managerPhone = account.Phone
			}
		} else {
			managerPhone = account.Phone
		}
		newBrokerPhone := loupan_utils.BatchAddBrokerPhoneToThisLouPan(brokers, managerPhone, phoneDnAudio.Broker)
		// 更新目的码
		if err = tx.Model(&phone.PhoneAudio{}).Where("id = ?", phoneDnAudio.ID).Updates(map[string]interface{}{
			"broker": fmt.Sprintf(",%v,", newBrokerPhone),
		}).Error; err != nil {
			return errors.New(e.ErrorInfo)
		}
		// 更新远端的400电话
		var list []*model.Row
		var aniAudio = ""
		var dniAudio = ""
		if phoneDnAudio.Audit == 2 { //审核通过就添加语音，不通过不添加
			aniAudio = fmt.Sprintf("%v_ani.wav", phoneDnAudio.ID)
			dniAudio = fmt.Sprintf("%v_dni.wav", phoneDnAudio.ID)
		}
		list = append(list, &model.Row{Dn: fmt.Sprintf("%v", phoneDnAudio.ID), Tel: strings.Join(strings.Split(newBrokerPhone, ","), "|"), TransType: "rnd", AniVoiceName: aniAudio, DniVoiceName: dniAudio})
		code := api.PhoneVirtual.AddOrEditPhone(list)
		if code != "0" {
			return errors.New(e.ErrorInfo)
		}
		return nil
	})
	return err
}

// 获取驻守在该楼盘的经纪人
func (*NewLouPan) FindBrokerNotGarrisonInThisLouPan(paginate *loupan_model.GetGarrison) (*utils.Page, error) {
	var newBrokers = make([]*loupan_model.CanAddBrokerInThisLouPan, 0)
	global.OC_DB.Model(&admin.Account{}).Select(fmt.Sprintf("`hft_accounts`.`id`,`hft_accounts`.`real_name`,`hft_accounts`.`phone`,`hft_accounts`.`avatar`,SUM( CASE WHEN `hft_account_lou_pan`.lou_pan_id  = %v THEN 1 ELSE 0 END ) AS havings", paginate.LouID)).Joins("LEFT JOIN `hft_account_lou_pan` ON `hft_accounts`.`id` = `hft_account_lou_pan`.`account_id` ").Where("role_id = ?", 33).Group("`hft_accounts`.`id`").Having("havings = ?", 0).Scopes(dao.Paginate(dao.Page(paginate.Page), global.OC_DB)).Scopes(dao.GetCount(global.OC_DB)).Find(&newBrokers)
	for _, v := range newBrokers {
		v.Avatar = global.OC_CONFIG.AliyunOSS.BucketUrl + v.Avatar
	}
	paginate.Data = newBrokers
	return &paginate.Page, nil
}

// 查询该楼盘的400电话
func (*NewLouPan) FindLouPanPhone(louID uint) (*loupan_model.PhoneConfig, error) {
	var audio *phone.PhoneAudio
	var isAudit int = 1
	var phone = &model.Row{Tel: "", Dn: "", TransType: "", AniVoiceName: "", DniVoiceName: ""}
	err := global.OC_DB.Select("id,lou_id,audit").Where("lou_id = ?", louID).First(&audio).Error
	if err == nil {
		phoneConf, err := api.PhoneVirtual.FirstPhone(fmt.Sprintf("%v", audio.ID))
		if err == nil {
			phone = phoneConf
		}
		isAudit = audio.Audit
	}
	var comeName = fmt.Sprintf("%v_ani.wav", audio.ID)
	var inName = fmt.Sprintf("%v_dni.wav", audio.ID)
	aniList := api.PhoneAudio.FindAudio(comeName, 100, 1)
	dniList := api.PhoneAudio.FindAudio(inName, 100, 1)
	var conf = &loupan_model.PhoneConfig{
		Audit:     isAudit,
		AniAudio:  &model.AudioRemote{Content: "", AuditStatus: 1, AuditComment: "", VoiceUrl: "", Name: ""},
		DniAudio:  &model.AudioRemote{Content: "", AuditStatus: 1, AuditComment: "", VoiceUrl: "", Name: ""},
		PhoneConf: phone,
	}
	if len(aniList) != 0 {
		conf.AniAudio = aniList[0]
	}
	if len(dniList) != 0 {
		conf.DniAudio = dniList[0]
	}
	return conf, nil
}

// 修改楼盘或者添加楼盘电话
func (*NewLouPan) AddPhoneForLou(lou_id uint, data *loupan_model.PhoneConfig) error {
	var dn int
	var phoneAudio *phone.PhoneAudio

	err := global.OC_DB.Where("lou_id = ?", lou_id).First(&phoneAudio).Error
	if err != nil {
		dn = loupan_dao.SelectMaxID(global.OC_DB)
		var lou *admin.LouPan
		err := global.OC_DB.First(&lou, lou_id).Error
		if err != nil {
			return errors.New(e.LouPanNotExist)
		}
		var city, _ = strconv.Atoi(strings.Split(lou.RegionLink[1:len(lou.RegionLink)-1], ",")[2])
		managerID, err := global.OC_REDIS.Get(fmt.Sprintf("SITE_LOGIN-%v", city)).Result()
		fmt.Println(managerID, city)
		if err != nil {
			return errors.New(e.ErrorInfo)
		}
		var broker []*admin.Account
		var phoneBroker string = ""
		global.OC_DB.Table("hft_account_lou_pan").Select("a.`id`,a.`phone`").Joins("LEFT JOIN hft_accounts as a on a.`id` = hft_account_lou_pan.`account_id`").Find(&broker)
		if len((broker)) == 0 {
			var account *admin.Account
			if err = global.OC_DB.Select("id, phone").First(&account, managerID).Error; err != nil {
				return errors.New(e.AccountNotExist)
			}
			phoneBroker = fmt.Sprintf(",%v,", account.Phone)
		} else {
			var phoneList []string
			for _, v := range broker {
				phoneList = append(phoneList, v.Phone)
			}
			phoneBroker = fmt.Sprintf(",%v,", strings.Join(phoneList, ","))
		}
		var audio = &phone.PhoneAudio{
			ID:         uint(dn),
			Audit:      1,
			LouPanName: lou.Name,
			LouID:      lou_id,
			Broker:     phoneBroker,
		}
		var phoneList = []*model.Row{
			&model.Row{
				Tel:          strings.Join(strings.Split(phoneBroker[1:len(phoneBroker)-1], ","), "|"),
				Dn:           fmt.Sprintf("%v", dn),
				AniVoiceName: "",
				DniVoiceName: "",
				TransType:    "rnd",
			},
		}
		code := api.PhoneVirtual.AddOrEditPhone(phoneList)
		if code != "0" {
			return errors.New(e.Phone400AddFail)
		}
		err = global.OC_DB.Transaction(func(tx *gorm.DB) error {
			err = tx.Create(&audio).Error
			if err != nil {
				return errors.New(e.ErrorInfo)
			}
			err = tx.Model(&admin.SellLouPanInfo{}).Where("lou_pan_id = ?", lou_id).Update("sell_phone", dn).Error
			if err != nil {
				return errors.New(e.ErrorInfo)
			}
			return nil
		})
		if err != nil {
			return err
		}
	} else {
		dn = int(phoneAudio.ID)
		global.OC_DB.Model(&phoneAudio).Where("id = ?", dn).Update("audit", "1")
	}
	var list = []*model.AudioName{
		&model.AudioName{Name: fmt.Sprintf("%v_ani.wav", dn)},
		&model.AudioName{Name: fmt.Sprintf("%v_dni.wav", dn)},
	}
	ok := api.PhoneAudio.DeleteAudio(list)
	if !ok {
		return errors.New(e.Phone400AddFail)
	}
	var newList = []*model.Audio{
		&model.Audio{Name: fmt.Sprintf("%v_ani.wav", dn), Content: data.AniAudio.Content},
		&model.Audio{Name: fmt.Sprintf("%v_dni.wav", dn), Content: data.DniAudio.Content},
	}
	res := api.PhoneAudio.UploadAudio(newList)
	if res != "0" {
		return errors.New(e.Phone400AddFail)
	}
	return nil
}

// 更新语音
func (*NewLouPan) UpdateAudioPhone(dn int) error {
	var audio *phone.PhoneAudio
	err := global.OC_DB.First(&audio, dn).Error
	if err != nil {
		return errors.New(e.ErrorInfo)
	}
	var list = []*model.Row{
		&model.Row{
			Tel:          strings.Join(strings.Split(audio.Broker[1:len(audio.Broker)-1], ","), "|"),
			Dn:           fmt.Sprintf("%v", audio.ID),
			TransType:    "rnd",
			AniVoiceName: fmt.Sprintf("%v_ani.wav", audio.ID),
			DniVoiceName: fmt.Sprintf("%v_dni.wav", audio.ID),
		},
	}
	errcode := api.PhoneVirtual.AddOrEditPhone(list)
	if errcode != "0" {
		return errors.New("审核尚未通过或者同步失败")
	} else {
		err := global.OC_DB.Model(&phone.PhoneAudio{}).Where("id = ?", dn).Update("audit", "2").Error
		if err != nil {
			return err
		}
	}
	return nil
}

var NewLouPanService = new(NewLouPan)
